package event

import (
	"net"
	"sync"
	"tinyGW/app/api/repository"
	"tinyGW/app/models"
	"tinyGW/pkg/service/command"
	"tinyGW/pkg/service/event"

	"go.uber.org/zap"
)

// ProtocolEventHandler 协议事件处理函数类型
// 参数：deviceAddr 设备地址, data 原始数据, variables 解析后的变量, conn 连接对象
//
// 这是一个通用的回调接口，所有协议处理都通过注册处理器来实现
// 不再有硬编码的协议逻辑
type ProtocolEventHandler func(
	deviceAddr string,
	data []byte,
	variables []models.DeviceProperty,
	deviceRepo repository.DeviceRepository,
	eventBus *event.EventService,
	commandManager *command.Manager,
	conn net.Conn,
)

var (
	// 协议事件处理器注册表
	protocolEventHandlers = make(map[string]ProtocolEventHandler)
	handlerMutex          sync.RWMutex
)

// RegisterProtocolEventHandler 注册协议事件处理器
// protocol: 协议名称（如 "2025F183-37", "Q3761-1376"）
// handler: 事件处理函数
//
// 示例：在plugin或业务层初始化时注册
//
//	event.RegisterProtocolEventHandler("MyProtocol", func(deviceAddr string, data []byte, ...) {
//	    // 1. 解析数据
//	    // 2. 更新设备状态
//	    // 3. 发布事件
//	    // 4. 处理指令队列
//	})
func RegisterProtocolEventHandler(protocol string, handler ProtocolEventHandler) {
	handlerMutex.Lock()
	defer handlerMutex.Unlock()

	protocolEventHandlers[protocol] = handler
	zap.S().Infof("✓ 注册协议事件处理器: %s", protocol)
}

// UnregisterProtocolEventHandler 注销协议事件处理器
func UnregisterProtocolEventHandler(protocol string) {
	handlerMutex.Lock()
	defer handlerMutex.Unlock()

	delete(protocolEventHandlers, protocol)
	zap.S().Infof("✗ 注销协议事件处理器: %s", protocol)
}

// HandleProtocolEvent 处理协议事件（通过注册的处理器）
// 这是一个通用的事件分发器，根据协议名称调用对应的处理器
//
// 如果协议没有注册处理器，则静默忽略（仅记录Debug日志）
func HandleProtocolEvent(
	protocol string,
	deviceAddr string,
	data []byte,
	variables []models.DeviceProperty,
	deviceRepo repository.DeviceRepository,
	eventBus *event.EventService,
	commandManager *command.Manager,
	conn net.Conn,
) {
	handlerMutex.RLock()
	handler, exists := protocolEventHandlers[protocol]
	handlerMutex.RUnlock()

	if exists && handler != nil {
		// 异步处理事件，避免阻塞主流程
		go func() {
			defer func() {
				if r := recover(); r != nil {
					zap.S().Errorf("协议事件处理器异常: protocol=%s, device=%s, error=%v", protocol, deviceAddr, r)
				}
			}()
			handler(deviceAddr, data, variables, deviceRepo, eventBus, commandManager, conn)
		}()
	} else {
		// 未注册的协议，仅记录调试日志
		zap.S().Debugf("协议 %s 没有注册事件处理器，跳过事件处理", protocol)
	}
}

// GetRegisteredProtocols 获取所有已注册的协议列表（用于调试）
func GetRegisteredProtocols() []string {
	handlerMutex.RLock()
	defer handlerMutex.RUnlock()

	protocols := make([]string, 0, len(protocolEventHandlers))
	for protocol := range protocolEventHandlers {
		protocols = append(protocols, protocol)
	}
	return protocols
}

// init 初始化
// 注意：不再有任何硬编码的协议处理器
// 协议处理器应该在业务层或plugin初始化时注册
func init() {
	zap.S().Info("📋 事件注册器初始化完成（纯plugin驱动模式）")
	zap.S().Info("💡 提示：协议处理器需要在应用启动时手动注册")
}

// 以下是一些辅助函数，用于简化事件处理器的实现

// NotifyDeviceOnline 通用的设备上线通知
func NotifyDeviceOnline(deviceAddr string, deviceRepo repository.DeviceRepository) {
	device, err := deviceRepo.FindByAddr(deviceAddr)
	if err != nil {
		zap.S().Debugf("设备 %s 不存在于数据库: %v", deviceAddr, err)
		return
	}

	device.Online = true
	deviceRepo.Save(&device)
	zap.S().Infof("设备 %s 上线", deviceAddr)
}

// NotifyDeviceData 通用的设备数据通知
func NotifyDeviceData(
	deviceAddr string,
	dataMap map[string]interface{},
	deviceRepo repository.DeviceRepository,
	eventBus *event.EventService,
) {
	device, err := deviceRepo.FindByAddr(deviceAddr)
	if err != nil {
		zap.S().Debugf("设备 %s 不存在于数据库: %v", deviceAddr, err)
		return
	}

	// 更新设备属性
	for i, prop := range device.Type.Properties {
		if value, exists := dataMap[prop.Name]; exists {
			device.Type.Properties[i].Value = value
			device.Type.Properties[i].Reported = true
		}
	}

	// 保存设备
	deviceRepo.Save(&device)

	// 发布事件
	eventBus.Publish(event.Event{
		Name: "DeviceCollectFinish",
		Data: device,
	})
}

// ProcessCommandQueue 通用的指令队列处理
func ProcessCommandQueue(
	deviceAddr string,
	commandManager *command.Manager,
	conn net.Conn,
) {
	if commandManager == nil {
		return
	}

	// 循环处理队列中的所有指令
	for command.GetQueueLength(deviceAddr) > 0 {
		data, ok := commandManager.Get(deviceAddr)
		if !ok {
			break
		}

		// 发送指令到设备
		_, err := conn.Write(data)
		if err != nil {
			zap.S().Errorf("发送指令到设备[%s]失败: %v", deviceAddr, err)
			break
		}

		// 从队列中移除已发送的指令
		commandManager.Remove(deviceAddr)
		zap.S().Debugf("发送指令到设备[%s]成功", deviceAddr)
	}
}
